
#include "init.h"
#include "m_menu.h"
#include "../teximage/keys.h"
#include "coid/comm/binstream/stdstream.h"

#include <windows.h>



int start_server( int argc, char *argv[] );
void loop_server( void (*callback)(void) );

int server_running = 0;


RSPC_CLASS_REG(W,bman_net::world_creator_fn);

////////////////////////////////////////////////////////////////////////////////
//C_World*     GW = 0;
//HPTIMER      Ghpt;

//fntRenderer  GTXT;
//fntTexFont   Gfont_courier;
//fntTexFont   Gfont_times;

PlayerProfile   GPlayerProfile;

WindowStatus    GWS;
bman_net        GW;

uint            TARGET_BPP = 32;

TexImage        SCREEN;
Font            FONT;

TexImage::ColorizedSpriteArray* Menu::_selimage = 0;
uint32          Menu::_colpri = 0x00ff0000;
uint32          Menu::_colsec = 0x00eeeeee;


////////////////////////////////////////////////////////////////////////////////
rsp_base* bman_net::world_creator_fn( rsp_base* ref )
{
    if(ref)  return &GW.CW;
    return new World;
}

////////////////////////////////////////////////////////////////////////////////
uint find_nearest_mode( uint flg, uint& x, uint& y )
{
    const uint XRES[] = { 640, 800, 1024, 1280, 0 };
    const uint YRES[] = { 480, 600, 768, 1024, 0 };

    uint bpp;
    for( uint m=0; XRES[m] != 0; ++m )
    {
        if( y > YRES[m]  ||  x > XRES[m] )
            continue;

        bpp = SDL_VideoModeOK( XRES[m], YRES[m], 16, flg );
        if( bpp != 15  &&  bpp != 16 )
            continue;

        x = XRES[m];
        y = YRES[m];
        return bpp;
    }

    return 0;
}

////////////////////////////////////////////////////////////////////////////////
void loop()
{
    teximage_process_events();
    
    if( GW.process_frame() )
    {
        GW.draw_screen(0);

        uint t1 = _Timer.time();
        SCREEN.flip();
        uint t2 = _Timer.time();
        
        if( t2-t1 > 3 ) {
            LOG(2) {
                *TLOG << timefmt(Gactive_controller->get_current_stateid() - RSPC_SETTINGS._nwaiting_states)
                << " frame blit " << (t2-t1) << "ms, ending at " << timefmt() << BINSTREAM_FLUSH;
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
int main( int argc, char **argv )
{
    netSubsystem::instance();
    stdoutstream sout;

    //if( 0 != SDL_Init(SDL_INIT_VIDEO) ) //SDL_INIT_AUDIO
    if( 0 != SDL_VideoInit( "directx", 0 ) )    //or "windib"
    {
        sout << "SDL initialization failed:\n" << SDL_GetError();
        return -1;
    }

    GWS.width = World::XTILES*TWpx;
    GWS.height = World::YTILES*TWpx;

    uint XRES = GWS.width;
    uint YRES = GWS.height;

    TARGET_BPP = 16;
    uint flg = SDL_HWSURFACE | SDL_DOUBLEBUF;// | SDL_ASYNCBLIT;
    //uint flg = SDL_SWSURFACE;// | SDL_ASYNCBLIT;

    if( flg & SDL_HWSURFACE )
        TexImage::sw_surfaces = false;
    else
        TexImage::sw_surfaces = true;

    int argi=1;

    GW.CW.load_profile( true );
    RSPC_SETTINGS.set_command_lag(0);


    bool fullscr = GW.CW._profile._fullscreen;
    if( argc>argi && token("-w") == argv[argi] )
        ++argi, fullscr = false;
    else if( argc>argi && token("-f") == argv[argi] )
        ++argi, fullscr = true;

    const SDL_VideoInfo* vi = SDL_GetVideoInfo();
    if(vi)
    {
        TARGET_BPP = vi->vfmt->BitsPerPixel;

        sout << "current video mode pixel bitcount: " << TARGET_BPP << "\n";
        if( fullscr || (TARGET_BPP != 15  &&  TARGET_BPP != 16) )
        {
            if(!fullscr)
                sout << "always using fullscreen mode for depths other than 15/16\n";

            flg |= SDL_FULLSCREEN;
            TARGET_BPP = find_nearest_mode( flg, XRES, YRES );

            if( TARGET_BPP == 0 )
            {
                sout << "can't initialize any appropriate fullscreen mode\n";
                return -1;
            }
        }        
    }

    opcd e;
    SDL_Surface* scr = SDL_SetVideoMode( XRES, YRES, TARGET_BPP, flg );
    if(!scr)
    {
        sout << "can't create main window, format: "
            << GWS.width << "x" << GWS.height << ":" << TARGET_BPP << " error: \n"
            << SDL_GetError();

        return -1;
    }

    vi = SDL_GetVideoInfo();

    if( GWS.width != XRES  ||  GWS.height != YRES )
    {
        SDL_Rect r;
        r.w = GWS.width;
        r.x = (XRES - r.w)/2;
        r.h = GWS.height;
        r.y = (YRES - r.h)/2;
        SDL_SetClipRect( scr, &r );
    }


    SCREEN.create( scr );
    FONT.load( "data/fnt/fnt.fnt" );

    teximage_cbk_onkeydown( keybfunc );
    teximage_cbk_onkeyup( keybupfunc );
    teximage_cbk_onkey( keyfunc );

    set_repeat_delay(30);

    e = GW.CW.init();

    if(!e)
    {
        if( GW.CW._profile._drawratehalf )
            sout << "setting halved draw rate as requested by the configuration file\n";

        GW.set_half_rate( GW.CW._profile._drawratehalf );

        //GW.addr = argc > argi  ?  argv[argi++] : "62.168.66.120";
        //e = GW.connect( GW.CW._profile._nick, GW.addr );
    }

    if(e)
    {
        sout << opcd_formatter(e) << BINSTREAM_FLUSH;
        return -1;
    }

    //
    //start_server( 1, 0 );
    //server_running = 1;

    while(1)
    {
        if( server_running )
            loop_server( &loop );
        else
            loop();
    }
    
    return 0 ;
}

////////////////////////////////////////////////////////////////////////////////
int __stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
    dynarray<char*> argv;

    token t = GetCommandLine();

    for(;;)
    {
        if( t[0] == '"' )
        {
            *argv.add(1) = (char*) t.ptr();
            t.skip_notchar( '"', 1 );
            if( t[0] == '"' )
            {
                *(char*)t.ptr() = 0;
                t.skip_ingroup( " \t", 1 );
            }

            continue;
        }

        token a = t.cut_left( " \t", -1 );
        if(a.is_empty())  break;

        *(char*)(a.ptr()+a.len()) = 0;
        *argv.add(1) = (char*) a.ptr();
    }

    SetPriorityClass( GetCurrentProcess(), 0x00008000 /*ABOVE_NORMAL_PRIORITY_CLASS*/ );
    //SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS );

    return main( argv.size(), argv.ptr() );
}
